Unreal C++ Multiplayer Master: Intermediate Game Development (1)

Date:     Updated:

카테고리:

Chapter 1 Puzzle Platforms - Connecting Players

01-1 Course Promo

  • So this course isn’t for beginners Like a lot of our courses, it actually requires that you have experience making a couple of games with Unreal and C++

01-2 Introduction to Puzzle Platforms

  • So, yeah, let’s get started in to this section where we’re going to be once again connecting between instances on the same machine or on the local network and getting a general overview of how the multiplayer space looks with unreal

01-3 Differences Between UE5 and UE4

  • So in this vignette we’ve seen how Unreal four and Unreal five are actually more similar than they at first appear

01-4 Connecting Two Players

two

set

modeworld

  • What happen Under the Hood? (1) Unreal loads the Map (2) The Map specifies a GameMode (3) The PlayerController joins the Map (4) It asks the GameMode to spawn a Pawn (5) The Pawn is linked th the PlayerController

01-5 How to Be an Active Student

  • (1) Lecture Project Changes (2) This Lecture Discussions (3) Course Slides (4) Udemy QnA, Please use brace to attach the code (5) Discord

01-6 Surveying the Multiplayer Space

type

  • Session-Based Stages (1) Discovery (2) Connection (3) Synchronisation

01-7 Meet the Client-Server Model

input

peer

server

person

connect

local

  • Connect error solution, 16:23
  • 데디케이티드 서버에 대한 정보는 오른쪽 링크를 참고하자 (참고), (참고), (참고)

01-8 Tips For Not Spawning

  • Connect error solution

01-9 Detecting Where Code is Running

actor

plat

move

diff

AMovingPlatform::AMovingPlatform()
{
	PrimaryActorTick.bCanEverTick = true;

	// Now this actor can move
	// 주의할 점은 생성자에서 무언가를 변경해도
	// 월드에 배치되거나 블루프린트로 생성된 오브젝트는 변경되지 않는다
	SetMobility(EComponentMobility::Movable);
}

void AMovingPlatform::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

	// The code that we write runs both on the server and the client in exactly the same way
	// The only difference being that there are some method calls that allow us to detect
	// Whether we are the client or whether we are the server
	// Namely that method call is has authority
	// If server returns true else return false
	if (HasAuthority())
	{
		FVector Location = GetActorLocation();
		Location += FVector(Speed * DeltaTime, 0, 0);
		SetActorLocation(Location);
	}
}

01-10 Authority and Replication

replication

replication2

void AMovingPlatform::BeginPlay()
{
	Super::BeginPlay();

	if (HasAuthority())
	{
		// 이 액터가 네트워크 클라이언트에 복제되는지 여부를 설정합니다
		SetReplicates(true);
		// 이 액터의 움직임이 네트워크 클라이언트에 복제되는지 여부를 설정합니다
		SetReplicateMovement(true);
	}
}
void AMovingPlatform::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

	//------------------------------------------------------------------------
	// 코드를 만약 이렇게 바꾸면 클라에서만 큐브가 움직인다
	// 하지만 서버가 기준이기 때문에 클라 캐릭터가 큐브가
	// 원래 있던 위치에 박치기 하면 충돌이 일어난다
	// 이 상태에서 만약 서버 캐릭터가 큐브위에 올라서면
	// 클라이언트 큐브가 서버 캐릭터를 옮길것이다 하지만
	// 진실은 서버 캐릭터와 서버 큐브는 안움직이고 있다
	// 본문에서는 이것을 아래와 같이 설명하고 있다
	// Unreal builds basically will move when something is attached to moves
	// Something when it's standing on top of something, then it moves
	//------------------------------------------------------------------------
	if (!HasAuthority())
	{
		FVector Location = GetActorLocation();
		Location += FVector(Speed * DeltaTime, 0, 0);
		SetActorLocation(Location);
	}
}

01-11 Widgets For FVector Properties

edit

class PUZZLEPLATFORMS_API AMovingPlatform : public AStaticMeshActor
{
	GENERATED_BODY()

	//..
	
	// 위의 사진 처럼 Target 다이아 몬드를 생성해주려면 어떻게 해야 하는가?
	// MakeEditWidget = true로 세팅해준다
	UPROPERTY(EditAnywhere, Meta = (MakeEditWidget = true))
	FVector TargetLocation;
};

01-12 Sending The Platform Back

if (HasAuthority())
{
	// Target Swap을 아래 코드처럼 거리기반으로 해주는 이유는 무엇인가?
	// Position 기반으로 코드를 작성하면 속도가 너무 빠를때 해당 Position을
	// 지나쳐 무한히 움직일 수 있기 때문이다
	FVector Location = GetActorLocation();
	float JourneyLength = (GlobalTargetLocation - GlobalStartLocation).Size();
	float JourneyTravelled = (Location - GlobalStartLocation).Size();

	if (JourneyTravelled >= JourneyLength)
	{
		// GlobalStartLocation은 Local 좌표인가 World 좌표인가?
		// World 좌표
		FVector Swap = GlobalStartLocation;
		GlobalStartLocation = GlobalTargetLocation;
		GlobalTargetLocation = Swap;
	}

	FVector Direction = (GlobalTargetLocation - GlobalStartLocation).GetSafeNormal();
	Location += Speed * DeltaTime * Direction;
	SetActorLocation(Location);
}

01-13 Set Up A Simple Puzzle

open

movement

01-14 Playing Over The Internet

net

hamachi

  • C:\UE_4.17\Engine\Binaries\Win64\UE4Editor.exe D:\Puzzle_Platforms\PuzzlePlatforms\PuzzlePlatforms.uproject 000.000.000.000 -game -log

01-15 Set Up A Platform Trigger

plat

bp

add

pad

APlatformTrigger::APlatformTrigger()
{
 	// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;

	// TriggerVolume 라는 이름으로 컴포넌트를 생성했다
	TriggerVolume = CreateDefaultSubobject<UBoxComponent>(FName("TriggerVolume"));
	if (!ensure(TriggerVolume != nullptr)) return;

	RootComponent = TriggerVolume;
}

01-16 Handling Overlap Events in C++

// 충돌 이벤트를 생성하기 위한 주요 과정을 설명하면?

// 1. Dynamic 등록
TriggerVolume->OnComponentBeginOverlap.AddDynamic(this, &APlatformTrigger::OnOverlapBegin);
TriggerVolume->OnComponentEndOverlap.AddDynamic(this, &APlatformTrigger::OnOverlapEnd);

// 2. 충돌 함수 정의
void APlatformTrigger::OnOverlapBegin(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
	UE_LOG(LogTemp, Warning, TEXT("Activated"));
}

void APlatformTrigger::OnOverlapEnd(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)
{
	UE_LOG(LogTemp, Warning, TEXT("Deactivated"));
}

col

01-17 Activating Platforms From Triggers

set

click

01-18 When To Use A GameInstance

ins

setins

ini

window

class PUZZLEPLATFORMS_API UPuzzlePlatformsGameInstance : public UGameInstance
{
	GENERATED_BODY()
	
public:
	UPuzzlePlatformsGameInstance(const FObjectInitializer& ObjectInitializer);

	// 이 함수에 대해 설명하면?
	// UGameInstance에 있는 함수를 오버라이딩한 함수이다
	virtual void Init();
};

01-19 Console Commands With Exec

press

class PUZZLEPLATFORMS_API UPuzzlePlatformsGameInstance : public UGameInstance
{
	GENERATED_BODY()
	
public:
	UPuzzlePlatformsGameInstance(const FObjectInitializer& ObjectInitializer);
	virtual void Init();
	
	// 이 함수의 용도는 무엇인가?
	// 콘솔 창에서 실행시킬 명령어를 정의한다
	UFUNCTION(Exec)
	void Host();

	UFUNCTION(Exec)
	void Join(const FString& Address);
};
  • logging to the screen unreal 라고 구글에 검색하면 디버깅 메시지 출력 가이드를 볼 수 있다

01-20 Hosting Servers With ServerTravel

level

actor

  • (1) Player controllers will connect in to the map (2) We’ve got three players all playing around in the same map (3) Server can execute a command called server travel and say, oh, there’s another map (4) All to move over their server, travel to map number two, in this case, Africa map (5) All the servers, one by one, have to reconnect to the new map and move themselves into the new map so the controllers don’t get destroyed They just get moved into a new map
void UPuzzlePlatformsGameInstance::Host()
{
	UEngine* Engine = GetEngine();
	if (!ensure(Engine != nullptr)) return;

	Engine->AddOnScreenDebugMessage(0, 2, FColor::Green, TEXT("Hosting"));

	UWorld* World = GetWorld();
	if (!ensure(World != nullptr)) return;

	// 이 함수의 역할은?
	// 월드 이동
	World->ServerTravel("/Game/ThirdPersonCPP/Maps/ThirdPersonExampleMap?listen"); // ?listen 구문이 없으면 어떻게 될까? 따로 공부하자
}

01-21 Joining Servers With ClientTravel

default

  • Understand the difference between client travel and server travel, Client travel that operates on a player controller level and it tells the individual player controller that it should move
void UPuzzlePlatformsGameInstance::Join(const FString& Address)
{
	UEngine* Engine = GetEngine();
	if (!ensure(Engine != nullptr)) return;

	Engine->AddOnScreenDebugMessage(0, 5, FColor::Green, FString::Printf(TEXT("Joining %s"), *Address));

	APlayerController* PlayerController = GetFirstLocalPlayerController();
	if (!ensure(PlayerController != nullptr)) return;

	// 이 함수의 용도는 무엇인가?
	// Client travel을 하기위한 용도
	PlayerController->ClientTravel(Address, ETravelType::TRAVEL_Absolute);
}

01-22 Sharing Your Game On itch.io

pack

  • https://itch.io/ 이 사이트는 스팀과 달리 무료로 게임을 배포해 볼 수 있다

itch

edit

zip

upload

up

view


맨 위로 이동하기

댓글남기기